package com.tagtraum.perf.gcviewer;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;

import org.eclipse.swt.internal.LONG;

import com.java.diagnostics.visualizer.data.DataPoint;
import com.java.diagnostics.visualizer.data.TupleData;
import com.java.diagnostics.visualizer.data.Variant;
import com.java.diagnostics.visualizer.impl.marshalling.Marshaller;
import com.java.diagnostics.visualizer.impl.marshalling.MarshallerImpl;
import com.tagtraum.perf.gcviewer.model.GCModel;

class DrawPanel extends JPanel{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private GCModel model;
    private boolean freeafter = false;
    private boolean freebefore = false;
    private boolean usedafter = false;
    private boolean usedbefore = false;
    private boolean totalafter = false;
    private boolean totalbefore = false;
    private boolean request = false;
    private boolean freed = false;
    private boolean since = false;
    private boolean AFcompleted = false;
    private boolean Mark = false;
    private boolean Sweep = false;
    private boolean Compact = false;
    private boolean Gccompleted = false;
    private boolean overhead = false;
    private boolean ZoomIn = false;
    private boolean ZoomOut = false;
    private boolean ZoomIn_y = false;
    private boolean ZoomOut_y = false;
    private boolean[] showmark ;
    private Variant[] variants;
    private TupleData[] tupledatas;
    private JButton[] btshow;
    private Color[] colors;
    private int mark =0;
	private int x1 = 0;
	private int y1 = 0;
	private int x2 = 0;
	private int y2 = 0;
	private float xpreinterval = 0;
	private float ypreinterval = 0;
	private float ypreintervalms = 0;
	private double preminX = 0;
	private double preminY = 0;
	private double preminY1 = 0;
	private boolean current = true;
	private int dragged =0;
	private boolean zoomout =false;
	double maxX = 0 ;
	double minX = 0;
	double minX1 = 0;
	double maxY = 0;
	double minY = 0;
	double maxY1 = 0;
	double minY1 = 0;
	private long originalinterval =0;
    public DrawPanel(GCModel model)
    {
    	this.model = model;
    	this.setLayout(new BorderLayout());
		//added by wenguang.huang 2014年3月2日 上午9:41:10
		Marshaller marshaller = model.getMarshaller();
		tupledatas =((MarshallerImpl)marshaller).getDataSet().getTupleData();
        variants=((MarshallerImpl)marshaller).getDataSet().getVariants();
		//added end by wenguang.huang 2014年3月2日 上午9:41:10
    	showmark = new boolean[tupledatas.length];
    	btshow = new JButton[tupledatas.length];
    	colors = new Color[tupledatas.length];
    	Box baseBox = Box.createHorizontalBox();
    	
    	Box verticalBox = Box.createVerticalBox(); 
    	
    	JPanel panelp = new JPanel();
    	JPanel panel = new JPanel();
    	panelp.add(panel);
		panel.setLayout(null);
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		//this.add(panel,BorderLayout.EAST);	
		
	  	for(int i=0;i<tupledatas.length;i++)
    	{
	  	    String labelString =tupledatas[i].getLabel();
	  	    String label1=labelString.substring(labelString.indexOf('.')+1);
	  	 
			colors[i]= new Color((new Double(Math.random()* 192)).intValue()+64,(new Double(Math.random() * 192)).intValue() +64,(new Double(Math.random() * 192)).intValue() +64);
    		btshow[i]= new JButton(label1);
    		
    		btshow[i].setName(String.valueOf(i));
    		btshow[i].setMaximumSize(new Dimension(240, 25));
    		btshow[i].setContentAreaFilled(false);
    		btshow[i].setBorder(BorderFactory.createDashedBorder(colors[i]));
    		verticalBox.add(btshow[i]);
    		verticalBox.add(Box.createVerticalStrut(2));
    		//mark=i;
    		showmark[i]=false; 
    		btshow[i].addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e){
                try
                {   
                	JButton bt=(JButton) e.getComponent();
                	int i=Integer.valueOf(bt.getName());
            
                	showmark[i] =!showmark[i];
                	repaint();
                	
                }catch(Exception ex){
                ex.printStackTrace();
                }
                }
                
            });
    		
    	}

		baseBox.add(verticalBox);
		verticalBox.setAlignmentY(Component.CENTER_ALIGNMENT);
		verticalBox.setAutoscrolls(true);
		baseBox.setBackground(Color.WHITE);
		JPanel temPanel=new JPanel();
		temPanel.setBackground(Color.WHITE);
		
		temPanel.add(baseBox);
		JScrollPane tempjsc= new JScrollPane(temPanel);
		
		
		
    	this.add(tempjsc,BorderLayout.EAST);
    	
    	addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent event) {
				Point p = event.getPoint();
				x1 = (int) p.getX();
				y1 = (int) p.getY();
				
			}

			public void mouseReleased(MouseEvent event) {
				Point p = event.getPoint();
				x2 = (int) p.getX();
				y2 = (int) p.getY();
				current = true;
				if(dragged ==1)
				{
					zoomout =true;
				    dragged =0;
				}
				repaint();
			}
		});
		addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseDragged(MouseEvent event) {
				Point p = event.getPoint();
				x2 = (int) p.getX();
				y2 = (int) p.getY();
				current = false;
				dragged=1;
				zoomout =false;
				repaint();
			}
		});
    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
      
        g2.setPaint(Color.gray);
      
        int leftX = 60;
        int topY = 40;
        int width = this.getWidth() -360;
        int height = this.getHeight() - 80;


        this.setBackground(Color.WHITE);
       
        g2.draw3DRect(leftX, topY, width, height, false);
        
        Stroke st  =g2.getStroke();   
  
        Stroke bs = new BasicStroke(1,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL,0,new float[]{3,1},0);   
        g2.setStroke(bs);
        g2.setColor(Color.gray);
        for (int i =height + topY -60;i>topY ;i=i-60)
           g2.drawLine(leftX, i, width+leftX, i);
  
 
		
		   
		
		
		
	
	if(xpreinterval ==0||x1>x2)
	{
		
        minX = tupledatas[0].getRawMinX();		
		minY = tupledatas[0].getRawMinY();
		for (TupleData tuple : this.tupledatas) 
		{
		    maxX = Math.max(maxX, tuple.getRawMaxX());
		    minX = Math.min(minX, tuple.getRawMinX());
			if(tuple.getLabel().substring(tuple.getLabel().lastIndexOf('.')+1).equals("times"))
			{
			  maxY1 = Math.max(maxY1, tuple.getRawMaxY());
			  minY1 = Math.min(minY1, tuple.getRawMinY());
			}
			else 
			{
		      maxY = Math.max(maxY, tuple.getRawMaxY());
		      minY = Math.min(minY, tuple.getRawMinY());
			}
		}
        if(minX ==0)
        {
        	minX= tupledatas[0].getRawMinX();        
        }
        minX1 =minX;
        originalinterval =(long) (maxX -minX);
	}
        if(zoomout&&(x1<x2))
        {
            minX = ((x1-leftX)*xpreinterval/60.0) + preminX;
            maxX = ((x2-leftX)*xpreinterval/60.0) + preminX;
            minY = (height+topY -y2)*ypreinterval/60.0 + preminY;
            maxY = (height+topY -y1)*ypreinterval/60.0 + preminY;   
            minY1 = (height+topY -y2)*ypreintervalms/60.0 + preminY1;
            maxY1 = (height+topY -y1)*ypreintervalms/60.0 + preminY1;   
            zoomout =false;
        }
		/*
        int count = timestamp.size();   
        int count1 = usedheapafter.size();
        System.out.println(count+"eee  " +count1);
        
        long interval=(long)timestamp.get(count -1)-(long)timestamp.get(0);
        */
		long interval =(long) (maxX -minX);	
        long interval1 = (long) (maxY - minY);
        
        //System.out.println(interval1 +"max" +interval);
        int xcount = width/60;
        int ycount = height/60;
        
        float xinterval =  (interval/((float)xcount));
        float yinterval =  (interval1/((float)ycount));

        
   
        //float yintervalms = model.Getgcinfo().getMaxms()/ycount;
        float yintervalms = (float) ((maxY1-minY1)/ycount);
        yinterval = yinterval-yinterval%100 +100;
        xinterval = (float) (xinterval -xinterval%0.5 +0.5);
        yintervalms = (float) (yintervalms -yintervalms%0.05 +0.05);
        xpreinterval =xinterval;
        ypreinterval =yinterval;
        ypreintervalms = yintervalms;
        preminX = minX;
        preminY = minY;
        preminY1 = minY1;
        float content =(float) (xinterval+minX-minX1);
        float content1 = (float) (yinterval+minY);
        float content2 = (float) (yintervalms+minY1);
        System.out.println("width:"+width+"xinterval:"+xinterval);
        DecimalFormat df = new DecimalFormat("0.00");
        
        for (int i =leftX +60;i<width + leftX;i=i+60)
        {
            g2.drawLine( i,topY , i,height+topY);
            //g2.drawString(String.valueOf(content),i , height + topY +20);
            // content = content +xinterval;
        }
        Font tempfont = g2.getFont();
        if(originalinterval>36000000)
        {
         for (int i =leftX +60;i<width + leftX;i=i+60)
         {            
             g2.drawString(String.valueOf(df.format(content/3600000.0)),i , height + topY +20);
             content = content +xinterval;
         }
         g2.setFont(new Font("Arial", 1, 16));
         g2.drawString("(time/hh)", leftX+width, topY+height+40);
         g2.setFont(tempfont);
        }
        else if(originalinterval>60000)
        {
         for (int i =leftX +60;i<width + leftX;i=i+60)
         {            
             g2.drawString(String.valueOf(df.format(content/60000.0)),i , height + topY +20);
             content = content +xinterval;
         }
         g2.setFont(new Font("Arial", 1, 16));
         g2.drawString("(time/mm)", leftX+width, topY+height+40);
         g2.setFont(tempfont);
        }
        else if(originalinterval>1000)
        {
        	 for (int i =leftX +60;i<width + leftX;i=i+60)
             {            
                 g2.drawString(String.valueOf(df.format(content/1000.0)),i , height + topY +20);
                 content = content +xinterval;
             }
             g2.setFont(new Font("Arial", 1, 16));
             g2.drawString("(time/mm)", leftX+width, topY+height+40);
             g2.setFont(tempfont);	
        }
        else
        {
          for (int i =leftX +60;i<width + leftX;i=i+60)
          {            
            g2.drawString(String.valueOf(df.format(content)),i , height + topY +20);
            content = content +xinterval;
          }
          g2.setFont(new Font("Arial", 1, 16));
          g2.drawString("(time/ss)", leftX+width, topY+height+40);
          g2.setFont(tempfont);
        }
       
        g2.setFont(new Font("Arial", 1, 16));
        g2.drawString("(time/ms)", leftX+width, topY-10); 
        g2.setFont(tempfont);
        
        DecimalFormat dfy = new DecimalFormat("0");
        if(interval1>10485760)
        {
          for (int i =height + topY-60;i>topY ;i=i-60)
          {           	
        	g2.drawString(String.valueOf(dfy.format(content1/1048576.0)), 0,i);
        	g2.drawString(String.valueOf(df.format(content2)), width+leftX, i);
            content1 = content1 +yinterval;
            content2 = content2 +yintervalms;
          }
          
          g2.setFont(new Font("Arial", 1, 16));
          g2.drawString("(size/mb)", 0, topY-10);
          g2.setFont(tempfont);
        }
        else if(interval1>10240)
        {
         for (int i =height + topY-60;i>topY ;i=i-60)
         {           	
            	g2.drawString(String.valueOf(dfy.format(content1/1024.0)), 0,i);
            	g2.drawString(String.valueOf(df.format(content2)), width+leftX, i);
                content1 = content1 +yinterval;
                content2 = content2 +yintervalms;
         }
         g2.setFont(new Font("Arial", 1, 16));
         g2.drawString("(size/kb)", 0, topY-10);
         g2.setFont(tempfont);
        }
        else 
        {
         for (int i =height + topY-60;i>topY ;i=i-60)
         {           	
            	g2.drawString(String.valueOf(dfy.format(content1)), 0,i);
            	g2.drawString(String.valueOf(df.format(content2)), width+leftX, i);
                content1 = content1 +yinterval;
                content2 = content2 +yintervalms;
         }
         g2.setFont(new Font("Arial", 1, 16));
         g2.drawString("(size/byte)", 0, topY-10);
         g2.setFont(tempfont);
        }
        

        g2.setColor(Color.red);
      
        
        for(int i =0;i<tupledatas.length;i++)
        {
        	

        	
        	if(showmark[i])
             {
               g2.setColor(colors[i]);
               DataPoint[] datapoints=tupledatas[i].getDataPoints();
               
               String label=tupledatas[i].getLabel();
               int count1=datapoints.length;
               
               for(int j =0;j <count1-1;j++)
               {
            	 
            	  if((long)datapoints[j+1].getRawX()>(long)maxX)
            		  break;
            	  if(label.substring(label.lastIndexOf('.')+1).endsWith("times"))
            	  {
            		  if((long)datapoints[j+1].getRawX()>(long)minX&&datapoints[j+1].getRawY()>minY1&&datapoints[j+1].getRawY()<maxY1&&
               			   datapoints[j].getRawX()>minX&&datapoints[j].getRawY()>minY1&&datapoints[j].getRawY()<maxY1)
               	   {
                	     int x1 = (int)(((long)datapoints[j].getRawX()-(long)minX)*(60.0/xinterval)) +leftX;
                	     int x2 = (int)(((long)datapoints[j+1].getRawX()-(long)minX)*(60.0/xinterval))+leftX;
                	     
                	    
                	     int y1 = (int)(height+topY-((datapoints[j].getRawY()-minY1)*(60.0/yintervalms)));
                    	 int y2 = (int)(height+topY-((datapoints[j+1].getRawY()-minY1)*(60.0/yintervalms))); 
                	     
                	     
                	                	 
                	
                	     g2.drawLine(x1, y1, x2, y2);
               	   }
            	  }
            	  else {
					
				
            	   if((long)datapoints[j+1].getRawX()>(long)minX&&datapoints[j+1].getRawY()>minY&&datapoints[j+1].getRawY()<maxY&&
            			   datapoints[j].getRawX()>minX&&datapoints[j].getRawY()>minY&&datapoints[j].getRawY()<maxY)
            	   {
             	     int x1 = (int)(((long)datapoints[j].getRawX()-(long)minX)*(60.0/xinterval)) +leftX;
             	     int x2 = (int)(((long)datapoints[j+1].getRawX()-(long)minX)*(60.0/xinterval))+leftX;
             	   
             	 
             	      int y1 = (int)(height+topY-(float)(((long)datapoints[j].getRawY()-(long)minY)*(60.0/yinterval)));
                	  int y2 = (int)(height+topY-(int)(((long)datapoints[j+1].getRawY()-(long)minY)*(60.0/yinterval))); 
					
             	                	 
             	
             	     g2.drawLine(x1, y1, x2, y2);
            	   }
            	  }
               }
             
             }
        	
        	
        }
       
    }
	protected void paintBorder(Graphics g) {
		if (current)
			return;
		g.setColor(getForeground());
		g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2),
				Math.abs(y1 - y2));
		System.out.println(" x1:"+x1+"x2: "+x2+" y1:"+y1+" y2:"+y2);
	}
	
}